package com.example.log4jdemo.config;

import jdk.jfr.Category;
import org.apache.logging.log4j.core.Core;
import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
import org.apache.logging.log4j.core.appender.rolling.RolloverDescription;
import org.apache.logging.log4j.core.appender.rolling.RolloverDescriptionImpl;
import org.apache.logging.log4j.core.appender.rolling.action.Action;
import org.apache.logging.log4j.core.appender.rolling.action.FileRenameAction;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
import org.apache.logging.log4j.core.lookup.StrSubstitutor;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Plugin(name = "MyConfigRolloverStrategy", category = Core.CATEGORY_NAME, printObject = true)
public class MyConfigRolloverStrategy extends DefaultRolloverStrategy {

    public static class Builder extends DefaultRolloverStrategy.Builder {
        public MyConfigRolloverStrategy build() {
            DefaultRolloverStrategy build = super.build();
            return new MyConfigRolloverStrategy(build.getMinIndex(), build.getMaxIndex(), build.isUseMax(),
                    build.getCompressionLevel(), build.getStrSubstitutor(), build.getCustomActions().toArray(new Action[0]),
                    build.isStopCustomActionsOnError(), tempCompressedFilePattern(build));
        }
    }

    @PluginBuilderFactory
    public static Builder newBuilder() {
        return new Builder();
    }

    public static final String DEFAULT_TIMEFORMAT = "HHmmssSSS";
    @PluginAttribute("timeFormat")
    private String timeFormat;

    protected MyConfigRolloverStrategy(int minIndex, int maxIndex, boolean useMax, int compressionLevel,
                                       StrSubstitutor strSubstitutor, Action[] customActions, boolean stopCustomActionsOnError,
                                       String tempCompressedFilePatternString) {
        super(minIndex, maxIndex, useMax, compressionLevel, strSubstitutor, customActions, stopCustomActionsOnError, tempCompressedFilePatternString);
    }

    protected MyConfigRolloverStrategy(DefaultRolloverStrategy d) {
        super(d.getMinIndex(), d.getMaxIndex(), d.isUseMax(), d.getCompressionLevel(), d.getStrSubstitutor(),
                d.getCustomActions().toArray(new Action[0]), d.isStopCustomActionsOnError(), tempCompressedFilePattern(d));
    }

    private static String tempCompressedFilePattern(DefaultRolloverStrategy d) {
        return d.getTempCompressedFilePattern() == null ? "" : d.getTempCompressedFilePattern().toString();
    }

    @Override
    public RolloverDescription rollover(RollingFileManager manager) throws SecurityException {
        RolloverDescription rolloverDescription = super.rollover(manager);
        FileRenameAction renameAction = newRenameAction(rolloverDescription);
        if (renameAction == null) {
            return rolloverDescription;
        }
        return new RolloverDescriptionImpl(rolloverDescription.getActiveFileName(), rolloverDescription.getAppend(),
                renameAction, rolloverDescription.getAsynchronous());
    }

    private FileRenameAction newRenameAction(RolloverDescription rolloverDescription) {
        FileRenameAction fileRenameAction = null;
        Action synchronous = rolloverDescription.getSynchronous();
        if (synchronous instanceof FileRenameAction action) {
            File destination = action.getDestination();
            String absolutePath = destination.getAbsolutePath();
            if (absolutePath.endsWith("SSS.log")) {
                System.out.println("timeFormat = " + timeFormat);
                String format = timeFormat == null ? DEFAULT_TIMEFORMAT : timeFormat;
                String time = DateTimeFormatter.ofPattern(format).format(LocalDateTime.now());
                String newName = absolutePath.replace("SSS.log", time + ".log");
                destination = new File(newName);
            }
            fileRenameAction = new FileRenameAction(action.getSource(), destination, action.isRenameEmptyFiles());
        }
        return fileRenameAction;
    }
}
